// dllmain.h : Declaration of module class.

static const WCHAR strRegistrationRoot[] = L"Software\\Microsoft\\VisualStudio\\10.0";

#ifdef _USRDLL

class CXortDebugEngineModule : public ATL::CAtlDllModuleT< CXortDebugEngineModule >
{
public :
	DECLARE_LIBID(LIBID_XortDebugEngineLib)
	DECLARE_REGISTRY_APPID_RESOURCEID(IDR_XORTDEBUGENGINE, "{34BC5F58-59AA-4FF5-B89A-1AB302E1B1EF}")
};

#else // executable 

class CXortDebugEngineModule : public ATL::CAtlExeModuleT< CXortDebugEngineModule >
{
private: 
    typedef CAtlExeModuleT< CXortDebugEngineModule > base;

public:
    DECLARE_LIBID(LIBID_XortDebugEngineLib)
    DECLARE_REGISTRY_APPID_RESOURCEID(IDR_XORTDEBUGENGINE, "{34BC5F58-59AA-4FF5-B89A-1AB302E1B1EF}")

    HRESULT RegisterServer( BOOL bRegTypeLib = FALSE, const CLSID *pCLSID = NULL )
    {
        SetMetric( metrictypeEngine, __uuidof(Engine), metricName, L"XortDebugEngine", false, strRegistrationRoot ); 
        SetMetric( metrictypeEngine, __uuidof(Engine), metricCLSID, CLSID_Engine, false, strRegistrationRoot ); 
        SetMetric( metrictypeEngine, __uuidof(Engine), metricProgramProvider, CLSID_MsProgramProvider, false, strRegistrationRoot );
        SetMetric( metrictypeEngine, __uuidof(Engine), metricDisassembly, 1UL, false, strRegistrationRoot );
        return base::RegisterServer( bRegTypeLib, pCLSID ); 
    }

    HRESULT UnregisterServer( BOOL bUnRegTypeLib, const CLSID *pCLSID = NULL )
    {
        RemoveMetric( metrictypeEngine, __uuidof(Engine), metricName, strRegistrationRoot ); 
        RemoveMetric( metrictypeEngine, __uuidof(Engine), metricCLSID, strRegistrationRoot ); 
        RemoveMetric( metrictypeEngine, __uuidof(Engine), metricProgramProvider, strRegistrationRoot ); 
        RemoveMetric( metrictypeEngine, __uuidof(Engine), metricDisassembly, strRegistrationRoot );
        return base::UnregisterServer( bUnRegTypeLib, pCLSID ); 
    }

    // unsafe calls!!! caller must verify the result
    inline IDebugEngine2 *        getEngineNoAddRef() { return m_spEngine; }
    inline IDebugProcess2 *       getProcessNoAddRef() { return m_spProcess; }
    inline IDebugThread2 *        getThreadNoAddRef() { return m_spThread; }
    inline IDebugProgram2 *       getProgramNoAddRef() { return m_spProgram; }
    inline IDebugEventCallback2 * getCallbackNoAddRef() { return m_spCallback; }
    inline IXProgram *            getXProgramNoAddRef() { CComQIPtr<IXProgram> spXP( m_spProgram ); return spXP.p; }

    inline void setEngine(  IDebugEngine2 *       p ) { m_spEngine   = p; }
    inline void setProcess( IDebugProcess2 *      p ) { m_spProcess  = p; }
    inline void setThread(  IDebugThread2 *       p ) { m_spThread   = p; }
    inline void setProgram( IDebugProgram2 *      p ) { m_spProgram  = p; }
    inline void setCallback(IDebugEventCallback2 *p ) { m_spCallback = p; }

    void ReleaseAllDebugObjects()
    {
        m_spEngine.Release();
        m_spProcess.Release(); 
        m_spThread.Release();
        m_spProgram.Release();
        m_spCallback.Release();
    }

    void SetMainThreadID() {
        m_dwMainThreadID = GetCurrentThreadId();
    }

    void PostMsgToMainThread( UINT iMsg, WPARAM wParam = 0, LPARAM lParam = 0 )
    {
        PostThreadMessage( m_dwMainThreadID, iMsg, wParam, lParam );
    }

private:
    CComPtr<IDebugEngine2>          m_spEngine;
    CComPtr<IDebugProcess2>         m_spProcess;
    CComPtr<IDebugThread2>          m_spThread;     // unused - for future
    CComPtr<IDebugProgram2>         m_spProgram;
    CComPtr<IDebugEventCallback2>   m_spCallback;

    DWORD                           m_dwMainThreadID;
};

#endif

extern class CXortDebugEngineModule _AtlModule;
